#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <arpa/inet.h>
#include <linux/un.h>
#include "ipc_socket.h"

#define EPOLL_EVENTS_NUM 10

#define MAX_CLIENT_SOCKET 10
#define SOCKET_NULL 0

int client_socket[MAX_CLIENT_SOCKET] = {SOCKET_NULL};

int client_socket_add(int socket_fd)
{
    int ret = -1;
    int i = 0;
    //check
    for(i = 0; i < MAX_CLIENT_SOCKET; i++) {
        if (client_socket[i] == socket_fd) {
            printf("client socket added\n");
            return socket_fd;
        }
    }
    //add
    for(i = 0; i < MAX_CLIENT_SOCKET; i++) {
        if(client_socket[i] == SOCKET_NULL) {
            client_socket[i] = socket_fd;
            ret = socket_fd;
            break;
        }
    }
    printf("Add socket success : %d\n", socket_fd);

    if(i >= MAX_CLIENT_SOCKET) {
        printf("client_socket over\n");
    }
    return ret;
}

int client_socket_del(int socket_fd)
{
    int ret = -1;
    int i = 0;
    for(i = 0; i < MAX_CLIENT_SOCKET; i++) {
        if(client_socket[i] == socket_fd) {
            client_socket[i] = SOCKET_NULL;
            ret = socket_fd;
        }
    }

    if(i >= MAX_CLIENT_SOCKET) {
        printf("del:client_socket can't find\n");
    }
    return ret;
}

void server_send_to(int socket_server, int socket_client, char *buff, int len)
{
    if((buff == NULL) || (len <= 0)){
        printf("parameters error\n");
    }

    for(int i = 0; i < MAX_CLIENT_SOCKET; i++) {
        if ((client_socket[i] != SOCKET_NULL) && (client_socket[i] != socket_client)) {
            len = send(client_socket[i], buff, len, 0);
            printf("[server_%04d] ==> [client_%04d] %03d: %s\n", socket_server, client_socket[i], len, buff);
        }
    }
}

void client_socket_close(void)
{
    int i = 0;
    for(i = 0; i < MAX_CLIENT_SOCKET; i++) {
        if(client_socket[i] != SOCKET_NULL) {
            client_socket[i] = SOCKET_NULL;
            close(client_socket[i]);
        }
    }
}

int main()
{
    int ret = -1;
    int fdEp = -1;
    int eventCount = 0;

    int server_fd = -1;
    char buff[128];
    server_fd = server_socket_init();
    if(server_fd == -1) {
        exit(0);
    }

    struct epoll_event eventfd;
    eventfd.data.fd = server_fd;
    eventfd.events = EPOLLIN;
    //创建epoll
    fdEp = epoll_create(MAX_CLIENT_SOCKET);
    if(fdEp == -1) {
        perror("epoll create");
        close(server_fd);
        return -1;
    }
    //将服务器socket加入监听
    ret = epoll_ctl(fdEp, EPOLL_CTL_ADD, server_fd, &eventfd);
    if (ret == -1) {
        perror("server epoll_ctl");
        close(server_fd);
        close(fdEp);
        return -1;
    }
    //创建监听事件队列
    struct epoll_event events[EPOLL_EVENTS_NUM];

    //初始化退出信号处理函数
    quit_signal_init();
    while(is_exit()) {
        eventCount = epoll_wait(fdEp, events, EPOLL_EVENTS_NUM, -1);
        if(eventCount == -1) {
            perror("epoll_wait");
            continue;
        }
        for(int i = 0; i < EPOLL_EVENTS_NUM; i++) {
            //如果是服务器socket，并且是读事件，则接收连接
            if(events[i].data.fd == server_fd) {
                if(events[i].events & EPOLLIN) {
                    int client_fd = server_socket_connect(server_fd);
                    if(client_fd == -1) {
                        continue;
                    }

                    ret = client_socket_add(client_fd);
                    if (ret == -1) {
                        close(client_fd);
                        continue;
                    }
                    //将客户端socket加入监听
                    eventfd.data.fd = client_fd;
                    eventfd.events = EPOLLIN;
                    ret = epoll_ctl(fdEp, EPOLL_CTL_ADD, client_fd, &eventfd);
                    if(ret == -1) {
                        perror("client epoll_ctl");
                        continue;
                    }
                }
            } else {
                //服务器socket接收数据
                if(events[i].events & EPOLLIN) {
                    int len = recv(events[i].data.fd, buff, sizeof(buff), 0);
                    if(len == 0) {
                        perror("server_recv");
                        epoll_ctl(fdEp, EPOLL_CTL_DEL, events[i].data.fd, NULL);
                        client_socket_del(events[i].data.fd);
                        close(events[i].data.fd);
                        continue;
                    } else if (len < 0) {
                        continue;
                    }
                    printf("[server_%04d] <== [client_%04d] %03d: %s\n", server_fd, events[i].data.fd, len, buff);
                    server_send_to(server_fd, events[i].data.fd, buff, len);
                }
            }
        }
    }
    close(fdEp);
    close(server_fd);
    client_socket_close();
    sprintf(buff, "rm %s", SOCKET_PATH);
    system(buff);
    return 0;
}
